﻿using System;
using System.Collections.Generic;
using System.Transactions;

namespace CMS.Business
{
    public abstract class BaseBussiness<T> : IBaseBussiness<T> where T : BaseViewModel
    {
        /// <summary>
        /// Gets or sets Common Key Value List business
        /// </summary>
        public IKeyValueList KeyValueList { get; set; }

        #region Method base common. Not edit, and override
        /// <summary>
        /// Method Save of object ViewModel T
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <param name="isTransaction">if set to <c>true</c> [is transaction].</param>
        /// <returns></returns>
        public T Save(T entity, bool isTransaction)
        {
            if (isTransaction)
            {
                Action(() =>
                {
                    if (entity.IsNew)
                    {
                        DoAdd(entity);
                        entity.IsNew = false;
                    }
                    else
                    {
                        DoUpdate(entity);
                    }
                });
            }
            else
            {
                if (entity.IsNew)
                {
                    DoAdd(entity);
                    entity.IsNew = false;
                }
                else
                {
                    DoUpdate(entity);
                }
            }

            return entity;
        }

        /// <summary>
        /// Delete with all info of object ViewModel
        /// </summary>
        /// <param name="entity">The entity.</param>
        public void Delete(T entity)
        {
            Action(() => DoDelete(entity));
        }

        /// <summary>
        /// Delete object by Id
        /// </summary>
        /// <param name="id">The id.</param>
        public void Delete(int id)
        {
            Action(() => DoDelete(id));
        }

        /// <summary>
        /// Select object. and set isNew=false
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns></returns>
        public T Select(int id)
        {
            T returnValue = DoSelect(id);
            returnValue.IsNew = false;

            return returnValue;
        }
                
        #endregion

        #region Private method

        /// <summary>
        /// Method will call have transaction. These methods are Add, Update, Delete.
        /// </summary>
        /// <param name="methodToDo">The method to do.</param>
        protected void Action(Action methodToDo)
        {
            // NhuDT 08/05/2013 add parameters to TransactionScope fix bug UAT 1922354.

            // No transaction is active
            TransactionOptions options = new TransactionOptions();
            options.IsolationLevel = System.Transactions.IsolationLevel.ReadCommitted;
            options.Timeout = new TimeSpan(0, 30, 0);

            using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Required, options))
            {
                try
                {
                    methodToDo();
                    transactionScope.Complete();
                }
                ////catch (Exception ex) 
                ////{
                ////    throw ex;
                ////}
                finally 
                {
                    transactionScope.Dispose();
                }
            }
        }
        #endregion

        #region Methos abstract must overide. If no, not built class

        protected abstract void DoAdd(T entity);

        protected abstract void DoUpdate(T entity);

        protected abstract void DoDelete(T entity);

        protected abstract void DoDelete(int id);

        protected abstract T DoSelect(int id);
        #endregion
    }
}
